Skip to content

drivers: video: mt9m114: Add vertical and horizontal flip control #81830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 12, 2024

Conversation

jeronimoagullo
Copy link
Contributor

This pull request gives support to flip the camera mt9m114 images horizontally and vertically. For this aim, it allows to modify camera buffer reading mode.

This PR provides support for the use of video_set_ctrl function with the Camera class control IDs of VIDEO_CID_HFLIP and VIDEO_CID_VFLIP.

It was proposed by @ngphibang during a conversation. thanks!

@zephyrbot zephyrbot added the area: Video Video subsystem label Nov 24, 2024
@ngphibang
Copy link
Collaborator

@jeronimoagullo : Thank you for the commit !
Could you point out the platform you tested this control and some hflipped / vflipped images of it ?

@jeronimoagullo
Copy link
Contributor Author

yes, @ngphibang I used the NXP imxRT1064 evaluation board. Besides, to check it out easily I modified the samples/drivers/video/tcpserversink sample to test it.

Copy link
Collaborator

@josuah josuah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Having the image in correct orientation is always needed...
I proposed some minor modification about error handling, but that is really not critical.

Comment on lines 400 to 401
ret |= mt9m114_write_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, sizeof(reg),
&reg);
Copy link
Collaborator

@josuah josuah Nov 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same proposal as below to turn this into ret = and immediately checking the error, which is a bit more verbose but helps avoiding subtle bugs in applications. I.e. checking if some operation is not supported (no point in retrying), or just some failure on I/O (a ladybug accidentally shorted the I2C.SDA and GND lines, ladybug forgiven and new attempt issued).

@jeronimoagullo
Copy link
Contributor Author

@josuah You are totally right! I was following the code style of the video drivers and I did't figure out the possibility of confusion due to error mess. I have modified it and push, please check it out, thanks!

josuah
josuah previously approved these changes Nov 24, 2024
Copy link
Collaborator

@josuah josuah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the change! It looks ready to land to me.
I was also using ret |= before Zephyr, as when the only error code is -1 this works.


switch (cid) {
case VIDEO_CID_HFLIP:
ret = mt9m114_set_horizontal_mirror(dev, (int)value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/mirror/flip/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the vim format of your comment!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)
Note that it of course doesn't apply if you end up refactoring the two functions into one

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kartben , as you said, this doesn't apply anymore due to refactoring (implemented differently), could you resolve the Change Request to help moving this PR forwards ?

}

if (enable) {
reg |= BIT(0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid magic numbers and #define this properly

}

if (enable) {
reg |= BIT(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

return mt9m114_write_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, sizeof(reg), &reg);
}

static int mt9m114_set_vertical_flip(const struct device *dev, int enable)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I missed something the two functions are after all essentially duplicated? Maybe make it a common set_orientation function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I used two different functions like other camera driver does, but in this case, the functions may be the same adding just the bit that you want to change. Thus, I will merge them into just one function

@kartben
Copy link
Collaborator

kartben commented Nov 25, 2024

Note that this will have conflicts when #78802 gets merged

@ngphibang
Copy link
Collaborator

The VIDEO_CID_HFLIP/VIDEO_CID_VFLIP CID naming are not changed in #78802 so I think it will not have conflicts.

BTW, I needs to test this PR on RT1064 before giving some reviews.

@jeronimoagullo
Copy link
Contributor Author

Note that this will have conflicts when #78802 gets merged

Are you sure? I have just added flip control. So, I use only from video-contro.h the VIDEO_CID_HFLIP and VIDEO_CID_VFLIP macros which are not modified in #78802. Thus, for the moment, both PRs shouldn't have conflicts, right?

@kartben
Copy link
Collaborator

kartben commented Nov 25, 2024

Note that this will have conflicts when #78802 gets merged

Are you sure? I have just added flip control. So, I use only from video-contro.h the VIDEO_CID_HFLIP and VIDEO_CID_VFLIP macros which are not modified in #78802. Thus, for the moment, both PRs shouldn't have conflicts, right?

ah yes sorry :) I thought all the macros had been renamed, but turns out these ones didn't have a category prefix in the first place. Sorry!

@@ -53,6 +55,10 @@ LOG_MODULE_REGISTER(video_mt9m114, CONFIG_VIDEO_LOG_LEVEL);
#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV (0 << 8)
#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB (1 << 8)

/* Camera control masks */
#define MT9M114_CAM_CONTROL_HORIZ_FLIP_EN BIT(0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest : MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN to be coherent with MT9M114_CAM_SENSOR_CTRL_READ_MODE and MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN

@@ -53,6 +55,10 @@ LOG_MODULE_REGISTER(video_mt9m114, CONFIG_VIDEO_LOG_LEVEL);
#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV (0 << 8)
#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB (1 << 8)

/* Camera control masks */
#define MT9M114_CAM_CONTROL_HORIZ_FLIP_EN BIT(0)
#define MT9M114_CAM_CONTROL_VERT_FLIP_EN BIT(1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest : MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN to be coherent with MT9M114_CAM_SENSOR_CTRL_READ_MODE

@@ -381,6 +387,26 @@ static int mt9m114_set_output_format(const struct device *dev, int pixel_format)
return ret;
}

static int mt9m114_set_orientation(const struct device *dev, int enable, uint8_t mask)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would drop this function. Just use mt9m114_modify_reg() directly as suggested in comments below

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that mt9m114_modify_reg() is used everywhere, this function can be removed.
Thanks for the modifications!


switch (cid) {
case VIDEO_CID_HFLIP:
ret = mt9m114_set_orientation(dev, (int)value, MT9M114_CAM_CONTROL_HORIZ_FLIP_EN);
Copy link
Collaborator

@ngphibang ngphibang Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN, (int)value ? MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN : 0);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point, but it is not feasible right now due to the definition of mt9m114_modify_reg function which works only with 8 bit registers. In this case, the MT9M114_CAM_SENSOR_CTRL_READ_MODE register is 16 bit.

I see two alternatives:

  1. rewrite function to work with 8, 16 and 32 bit registers
  2. write a function for each register size

Then, it would be feasible

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mt9m114_modify_reg() actually works with 16 bits registers. It 's just a combination of mt9m114_read_reg() and mt9m114_write_reg():

mt9m114_modify_reg(const struct device *dev, const uint16_t addr, const uint8_t mask,
			      const uint8_t val)

Copy link
Collaborator

@ngphibang ngphibang Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, I just double checked. Indeed, inside mt9m114_modify_reg , it calls read/write on 8-bit regs only:

uint8_t newVal;
int ret = mt9m114_read_reg(dev, addr, sizeof(oldVal), &oldVal);

Copy link
Collaborator

@ngphibang ngphibang Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if possible, could you also modify mt9m114_modify_reg so that it supports both 8 bits and 16 bits (and 32 bits) ? then mt9m114_modify_reg is only used here and on MT9M114_RST_AND_MISC_CONTROL in software reset so the changes will not be much ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it becomes interesting to have a CCI (Camera Common Interface) library that has read/write/modify built-in for various sizes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it is beyond the scope of this pull request, but it is something interested. However, right now we are using only an i2c bus. Thus, it would be interesting in case that we can configure cameras with other buses like SPI, otherwise, I don't see the point.

Copy link
Collaborator

@josuah josuah Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes absolutely, not related to this PR! I am thinking in the background: someone with a camera sensor knows the I2C address to toggle a feature and wants it upstream: how to make it just a 1-line diff to facilitate contribution.

I agree though: good not to introduce unneeded abstraction.
The way it is done here is probably the best solution.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josuah I think adding CCI would be helpful. But even with CCI, in Linux, camera drivers still uses different i2c APIs to read / write registers, so it will not make it a "standard way" for every drivers

Copy link
Collaborator

@josuah josuah Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this is now proposed here to save effort while writing/modifying new drivers:

ret = mt9m114_set_orientation(dev, (int)value, MT9M114_CAM_CONTROL_HORIZ_FLIP_EN);
break;
case VIDEO_CID_VFLIP:
ret = mt9m114_set_orientation(dev, (int)value, MT9M114_CAM_CONTROL_VERT_FLIP_EN);
Copy link
Collaborator

@ngphibang ngphibang Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN, (int)value ? MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN : 0);

@jeronimoagullo jeronimoagullo force-pushed the mt9m114_flip branch 3 times, most recently from 217c401 to c7568e2 Compare November 25, 2024 18:01
Copy link
Collaborator

@josuah josuah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more minor step...

This fixes mt9m114_modify_reg() which did not accept a size parameter.

@@ -381,6 +387,26 @@ static int mt9m114_set_output_format(const struct device *dev, int pixel_format)
return ret;
}

static int mt9m114_set_orientation(const struct device *dev, int enable, uint8_t mask)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that mt9m114_modify_reg() is used everywhere, this function can be removed.
Thanks for the modifications!

@jeronimoagullo jeronimoagullo force-pushed the mt9m114_flip branch 2 times, most recently from fd175f5 to a5e2c0d Compare November 26, 2024 08:22
@jeronimoagullo
Copy link
Contributor Author

jeronimoagullo commented Nov 26, 2024

@josuah check it out now, I have removed the mt9m114_set_orientation function and did a git rebase to be inline with main branch. I have tested it in the imxRT1064 successfully :)

loicpoulain
loicpoulain previously approved these changes Nov 26, 2024
Copy link
Collaborator

@ngphibang ngphibang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeronimoagullo Just a few things left then it will be OK. Thanks for the changes !

@@ -261,20 +267,21 @@ static int mt9m114_read_reg(const struct device *dev, uint16_t reg_addr, uint8_t
return 0;
}

static int mt9m114_modify_reg(const struct device *dev, const uint16_t addr, const uint8_t mask,
const uint8_t val)
static int mt9m114_modify_reg(const struct device *dev, const uint16_t addr,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the extension of mt9m114_modify_reg() should go into a separate commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, I should create a separate commit for it, merge it and then carry on with this PR. Do you agree?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, just split the current commit into 2 commits then force-push in this same PR.

@@ -297,15 +304,15 @@ static int mt9m114_write_all(const struct device *dev, struct mt9m114_reg *reg)

static int mt9m114_software_reset(const struct device *dev)
{
int ret = mt9m114_modify_reg(dev, MT9M114_RST_AND_MISC_CONTROL, 0x01, 0x01);
int ret = mt9m114_modify_reg(dev, MT9M114_RST_AND_MISC_CONTROL, 1, 0x01, 0x01);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MT9M114_RST_AND_MISC_CONTROL seems a 16-bit register ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are rigth! I have checkout the datasheet and it is 16 bit. I got confused since it was being modified by the 8-bit function like it was an 8-bit register. I will update it correctly.

ngphibang
ngphibang previously approved these changes Nov 26, 2024
josuah
josuah previously approved these changes Nov 26, 2024
@ngphibang ngphibang self-assigned this Nov 27, 2024
@jeronimoagullo
Copy link
Contributor Author

Hi! @kartben and @loicpoulain do you agree with the final version of the Pull Request? Thanks!

loicpoulain
loicpoulain previously approved these changes Dec 1, 2024
Copy link
Collaborator

@loicpoulain loicpoulain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ngphibang
Copy link
Collaborator

@jeronimoagullo Please rebase your branch on the lastest main to resolve the conflict.

@ngphibang
Copy link
Collaborator

@jeronimoagullo hey, can you do a (simple) git rebase to resolve the conflict ? It's because the #82301 was merged.

…ngth

Update mt9m114_modify_reg to support 8, 16 and 32 bits registers

Signed-off-by: Jeronimo Agullo <jeronimoagullo97@gmail.com>
Add set_ctrl function API for vertical and horizontal flip control
modifying the camera read mode

Signed-off-by: Jeronimo Agullo <jeronimoagullo97@gmail.com>
@ngphibang ngphibang requested a review from josuah December 10, 2024 08:47
@ngphibang
Copy link
Collaborator

@kartben Could you revisit this ? thanks !

@kartben
Copy link
Collaborator

kartben commented Dec 12, 2024

@kartben Could you revisit this ? thanks !

Of course, sorry!

@kartben kartben merged commit b69004c into zephyrproject-rtos:main Dec 12, 2024
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants